if __name__ == '__main__':    
    from config import Configuration
    import os,sys
    cur_dir=os.path.dirname(__file__)
    sys.path.append(os.path.dirname(cur_dir))
    import notifiers
else:
    from .config import Configuration
    import notifiers 

from datetime import datetime
from threading import Thread
import time

class Clock:
    def __init__(self,*,async_notify=True,deamon=True,debug=False,speed_radio=3) -> None:

        self.notifiers={}

        self.debug=debug
        self.configuratin=Configuration()
        self.add_notifiers()
        self._running=True
        self.daemon=deamon
        self.speed_radio=speed_radio
        self.async_notify=async_notify
        self.count_down_tread=None
        # self.state='running'

    def add_notifiers(self):
        valid_notifiers=[]
        # self.log(dir(notifiers))
        for cls_name in dir(notifiers):
            if 'Notifier' in cls_name:
                cls=getattr(notifiers,cls_name)
                key=cls_name.lower().replace('notifier','')
                self.notifiers[key]=cls()
                valid_notifiers.append(key)
                if key not in self.configuratin.notifiers:
                    self.configuratin.notifiers[key]=True
        
        #删除不存在的notifier

        for key in list(self.configuratin.notifiers.keys()):
            if key not in valid_notifiers:
                del self.configuratin.notifiers[key]


    @property
    def running(self):
        return self._running
    
    @running.setter
    def running(self,value):
        if self._running==value:
            return
        if value:
            self.start()
        else:
            self.stop()
            
    
    def stop(self):
        self._running=False
        self.count_down_tread.join()
        self.count_down_tread=None
        self.log('Clock stopped!')

    def get_remain_seconds(self):
        if self.running==False:
            return -1
        now=datetime.now()
        # hour=now.hour
        minute=now.minute
        second=now.second
        total_seconds=0
        for tick in self.configuratin.ticks:
            if minute < tick:
                total_seconds=(tick-minute)*60-second
                break
        else:
            total_seconds=(self.configuratin.ticks[0]+60-minute)*60-second
        return total_seconds
    
    
    def _count_down(self):
        if not self.running:
            return
        remain_seconds=self.get_remain_seconds()
        while remain_seconds>0:
            if not self.running:
                break
            if self.debug:
                print('remain seconds:',remain_seconds)
                remain_seconds=remain_seconds//self.speed_radio
            time.sleep(1)
            remain_seconds-=1
            if not self.debug and remain_seconds % 30==5:
                remain_seconds=self.get_remain_seconds()

        if not self.running:
            self.log('Clock is stopped, skip countdown!')
            return
        self.log(datetime.now(),'count down over!')
        self.notify()
        self._count_down()
    
    def start(self):
        self._running=True
        # time.sleep(1)
        t=Thread(target=self._count_down)
        self.count_down_tread=t
        t.daemon=self.daemon
        t.start()
        self.log('Start clock!')


    
    def notify(self):
        if not self.running:
            return
        for key in self.configuratin.notifiers:
            if self.configuratin.notifiers[key]:
                notifier=self.notifiers.get(key,None)
                if notifier==None:
                    self.log('Can not get notifier:',notifier)
                    continue
                if self.async_notify:
                    notifier.notify_async()
                else:
                    notifier.notify()
        
        #delay time
        time.sleep(1)

    
    def update_settings(self,settings):
        self.log('update config',settings)
        state= self.configuratin.update(settings)
        return state

    def wait(self):
        if self.count_down_tread:
            self.count_down_tread.join()
    
    def log(self,*args):
        if self.debug:
            print(*args)
    
 
    

if __name__ == '__main__':

    clock=Clock(debug=True)
    # clock.daemon=False
    clock.start()
    time.sleep(2)
    clock.running=False
    time.sleep(1)
    clock.running=True
    clock.wait()



    
